package com.fangcang.directlink.service.impl;

import com.alibaba.fastjson.JSON;
import com.fangcang.common.util.DateUtil;
import com.fangcang.common.util.PropertyCopyUtil;
import com.fangcang.directlink.service.SyncRedisService;
import com.fangcang.product.domain.IncreaseDO;
import com.fangcang.product.dto.IncreaseDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class SyncRedisServiceImpl implements SyncRedisService {

    @Autowired
    private RedisTemplate redisTemplate;

    private void selectDB(int dbIndex){
        LettuceConnectionFactory jedisConnectionFactory = (LettuceConnectionFactory) redisTemplate.getConnectionFactory();
        jedisConnectionFactory.setDatabase(dbIndex);
        redisTemplate.setConnectionFactory(jedisConnectionFactory);
    }

    @Override
    public Integer getPriceId(Integer pricePlanId, Date saleDate) {
        selectDB(1);//本类实例化的redisTemplate都会被修改为了1，其他类注册的redisTemplate会不会被同时修改index=1了呢？
        ValueOperations<String,Integer> valueOperations = redisTemplate.opsForValue();
        String key = getKey4PriceInfoId(pricePlanId,saleDate);
        Integer priceInfoId = valueOperations.get(key);
        return priceInfoId;
    }

    @Override
    public IncreaseDTO getIncreaseByChannel(Integer pricePlanId, Date saleDate, String channelCode) {
        selectDB(1);
        ListOperations<String,IncreaseDTO> increaseOps = redisTemplate.opsForList();

        String increaseKey = "incr:"+channelCode+":"+pricePlanId;
        List<IncreaseDTO> increaseDTOList = increaseOps.range(increaseKey,0,-1);

        if (CollectionUtils.isEmpty(increaseDTOList)){
            log.error("价格计划{}在{}渠道{}没有加幅",pricePlanId,saleDate,channelCode);
            return null;
        }

        IncreaseDTO result = null;
        Integer increaseId = 0;
        for (IncreaseDTO increaseDTO : increaseDTOList) {
            Date startDate = increaseDTO.getStartDate();
            Date endDate = increaseDTO.getEndDate();
            if (DateUtil.between(saleDate,startDate,endDate)){
                if (increaseDTO.getId() > increaseId){
                    result = increaseDTO;
                }
            }
        }

        return result;
    }

    @Override
    public Integer getQuotaAccountId(Integer pricePlanId) {
        selectDB(1);//本类实例化的redisTemplate都会被修改为了1，其他类注册的redisTemplate会不会被同时修改index=1了呢？
        ValueOperations<String,Integer> valueOperations = redisTemplate.opsForValue();
        String key = "pqa:"+pricePlanId;
        Integer quotaAccountId = valueOperations.get(key);
        return quotaAccountId;
    }

    @Override
    public Integer getQuotaId(Integer pricePlanId, Date saleDate) {
        selectDB(1);
        ValueOperations<String,Integer> valueOperations = redisTemplate.opsForValue();
        String key = getKey4QuotaId(pricePlanId,saleDate);
        Integer quotaId = valueOperations.get(key);
        return quotaId;
    }

    @Override
    public Integer getRestrictId(Integer pricePlanId) {
        selectDB(1);
        ValueOperations<String,Integer> valueOperations = redisTemplate.opsForValue();
        String key = "restrict:"+pricePlanId;
        Integer restrictId = valueOperations.get(key);
        return restrictId;
    }

    @Override
    public void saveIncrease(List<IncreaseDO> increaseList) {
        if (CollectionUtils.isEmpty(increaseList)){
            log.info("保存加幅到缓存：没有加幅数据要保存，直接返回。");
            return ;
        }

        try {
            //1-将increaseList 按照 pricePlanId,channelCode 进行分类。
            Map<String,List<IncreaseDTO>> increaseMap = new HashMap<>();
            increaseList.forEach(increaseDO -> {
                String channelCodePricePlanKey = increaseDO.getChannelCode()+":"+increaseDO.getPriceplanId();
                if (increaseMap.containsKey(channelCodePricePlanKey)){
                    increaseMap.get(channelCodePricePlanKey).add(PropertyCopyUtil.transfer(increaseDO,IncreaseDTO.class));
                } else{
                    List<IncreaseDTO> tempIncreaseList = new ArrayList<>();
                    tempIncreaseList.add(PropertyCopyUtil.transfer(increaseDO,IncreaseDTO.class));
                    increaseMap.put(channelCodePricePlanKey,tempIncreaseList);
                }
            });

            //2-保存到缓存中去
            selectDB(1);
            ListOperations<String,IncreaseDTO> increaseOps = redisTemplate.opsForList();

            for (Map.Entry<String,List<IncreaseDTO>> entry : increaseMap.entrySet()){
                String increaseKey = "incr:"+entry.getKey();
                List<IncreaseDTO> increaseDTOList = entry.getValue();
                increaseDTOList.forEach(increaseDTO -> {
                    increaseOps.leftPush(increaseKey,increaseDTO);
                });
//                List<IncreaseDTO> increaseDTOS = increaseOps.range(increaseKey,0,-1);
            }


        } catch (Exception e){
            log.error("保存加幅到缓存失败：{}", JSON.toJSONString(increaseList),e);
        }

    }

    private String getKey4PriceInfoId(Integer pricePlanId, Date saleDate){
        return getKey4Primkey("price",pricePlanId,saleDate);
    }
    private String getKey4QuotaId(Integer pricePlanId, Date saleDate){
        return getKey4Primkey("quota",pricePlanId,saleDate);
    }

    private String getKey4RestrictId(Integer pricePlanId, Date saleDate){
        return getKey4Primkey("restrict",pricePlanId,saleDate);
    }

    private String getKey4Primkey(String prefix,Integer pricePlanId, Date saleDate){
        return prefix + ":" + pricePlanId+":"+ DateUtil.dateToString(saleDate,"yyyyMMdd");
    }
}
